package com.cc.visitor.service;

import com.cc.alltype.BusinessException;
import com.cc.visitor.dao.EmployeeMapper;
import com.cc.visitor.dao.LogMiniMapper;
import com.cc.visitor.dao.UserWeixinMapper;
import com.cc.visitor.entity.Employee;
import com.cc.visitor.entity.LogMini;
import com.cc.visitor.entity.UserWeixin;
import com.cc.visitor.enums.RoleType;
import com.cc.visitor.enums.UserType;
import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.Transient;
import java.util.List;
import java.util.Optional;
import static com.cc.visitor.entity.table.UserWeixinTableDef.USER_WEIXIN;

/**
 * @author chanchaw
 * @create 2024-09-17 17:09
 */
@Service
public class UserWeixinServiceImpl implements UserWeixinService{
    @Autowired
    private EmployeeMapper employeeMapper;
    @Autowired
    private UserWeixinMapper dao;
    @Autowired
    private UserWeixinChecker checker;
    @Autowired
    private LogMiniMapper logMiniMapper;
    @Override
    public UserWeixin select8OpenId(String openId){
        QueryWrapper queryWrapper = QueryWrapper.create().select()
                .where(USER_WEIXIN.OPEN_ID.eq(openId));
        return dao.selectOneByQuery(queryWrapper);
    }
    @Override
    public List<UserWeixin> selectAll() {
        return dao.selectAll();
    }
    @Override
    public UserWeixin select8Primary(Integer id){
        return dao.selectOneById(id);
    }

    @Override
    public UserWeixin select8Type(Integer type){
        QueryWrapper queryWrapper = QueryWrapper.create().select().from(USER_WEIXIN).where(USER_WEIXIN.TYPE.eq(type));
        System.out.println("服务实现类中的类加载器：" + UserWeixin.class.getClassLoader());
        return dao.selectOneByQuery(queryWrapper);
    }

    /**
     * 用户在注册页面主动提交时用到，如非法会抛出异常提示用户
     * @param record
     * @return
     */
    @Override
    public UserWeixin insert(UserWeixin record){
        String openId = Optional.ofNullable(record.getOpenId()).orElse("");
        // 当前 openId 已经存在则恢复为可用状态并返回该用户数据
        if(!checker.restore2Valid(openId)) return dao.get8OpenId(openId);
        int i = dao.insertSelective(record);
        return dao.selectOneById(record.getId());
    }

    // 微信小程序新增用户用
    @Override
    public UserWeixin insertMini(UserWeixin record){
        String miniId = Optional.ofNullable(record.getMiniId()).orElse("");
        if(miniId.length() == 0) throw new BusinessException("没有微信小程序id，无法新增！");
        dao.insertSelective(record);
        return dao.selectOneById(record.getId());
    }

    @Override
    public UserWeixin update(UserWeixin record){
        dao.update(record);
        return dao.selectOneById(record.getId());
    }
    @Override
    public int delete(Integer id){
        return dao.deleteById(id);
    }
    @Override
    public UserType getUserType(String openId){
        UserWeixin userWeixin = dao.get8OpenId(openId);
        if(userWeixin == null) return UserType.VISITOR;
        Integer type = Optional.ofNullable(userWeixin.getType()).orElse(0);
        if(type.equals(0)) return UserType.VISITOR;
        return UserType.INTERVIEWEE;
    }

    /**
     * 判断微信用户是否开发人员
     * @param openId 微信 openId
     * @return true表示开发人员
     */
    @Override
    public Boolean isDev(String openId){
        QueryWrapper queryWrapper = QueryWrapper.create().select()
                .where(USER_WEIXIN.OPEN_ID.eq(openId));
        UserWeixin userWeixin = dao.selectOneByQuery(queryWrapper);
        Integer type = userWeixin.getType();
        return type >= 40 ? true : false;
    }

    /**
     * 新用户关注时使用，当前只有用户 openId 和 userType
     * 检测 openId 是否已经存在，是则查询DB并返回
     * 相反则新增新用户
     * @param record
     * @return
     */
    @Transactional
    @Override
    public UserWeixin insert8openId(UserWeixin record){
        if(record == null) return record;
        record.setId(null);
        String openId = Optional.ofNullable(record.getOpenId()).orElse("");

        QueryWrapper queryWrapper = QueryWrapper.create().select()
                .where(USER_WEIXIN.OPEN_ID.eq(openId));
        UserWeixin userWeixin = dao.selectOneByQuery(queryWrapper);
        if(userWeixin != null) return userWeixin;

        int i = dao.insertSelective(record);
        return dao.selectOneById(record.getId());
    }

    /**
     * 通过关注微信服务号已经在 user_weixin 中新增过一行数据后
     * 又在小程序中注册新用户，则调用本方法。
     * 注意此处的 openId = miniId
     * @param userWeixin 微信用户信息
     * @return
     */
    @Override
    public UserWeixin insert8mini(UserWeixin userWeixin){
        String openId = userWeixin.getOpenId();
        return null;
    }

    /**
     * 根据微信小程序ID查询获取用户信息
     * @param miniId
     * @return
     */
    @Override
    public UserWeixin select8MiniId(String miniId){
        return dao.get8MiniId(miniId);
    }

    // 有则修改，无则新增
    @Transactional
    @Override
    public UserWeixin saveMini(UserWeixin record){
        String unionId = Optional.ofNullable(record.getUnionId()).orElse("");
        if(unionId.length() == 0) {
            LogMini logMini = LogMini.builder().page("小程序新增用户时异常").func("UserWeixinServiceImpl#saveMini").category("java")
                    .remark("小程序中新增用户时由于unionId是空无法新增用户").build();
            logMiniMapper.insertSelective(logMini);
            throw new BusinessException("网络故障，请稍后再试！");
        }

        String miniId = Optional.ofNullable(record.getMiniId()).orElse("");
        String openId = Optional.ofNullable(record.getOpenId()).orElse("");

        UserWeixin userWeixinDB = dao.get8UnionId(unionId);
        Boolean isNew = false;
        if(userWeixinDB == null) {
            isNew = true;
            userWeixinDB = new UserWeixin();
        }
        if(openId.length() > 0) userWeixinDB.setOpenId(openId);
        userWeixinDB.setMiniId(miniId);
        userWeixinDB.setUnionId(unionId);
        userWeixinDB.setRegister(1);// 表示通过微信小程序注册功能主动提交
        userWeixinDB.setCompany(record.getCompany());
        userWeixinDB.setRealName(record.getRealName());
        userWeixinDB.setNickName(record.getNickName());
        userWeixinDB.setIdNumber(record.getIdNumber());
        userWeixinDB.setPhone(record.getPhone());
        userWeixinDB.setDepartment(record.getDepartment());
        userWeixinDB.setPosition(record.getPosition());
        userWeixinDB.setSubscribeTime(record.getSubscribeTime());
        userWeixinDB.setType(record.getType());// 小程序提交注册信息时传递来的用户类型
        if(isNew) insertMini(userWeixinDB);
        else dao.update(userWeixinDB);
        Integer id = Optional.ofNullable(userWeixinDB.getId()).orElse(0);
        UserWeixin userWeixin = dao.selectOneById(id);
        sync2Employee(userWeixin);// 如果当前注册的是受访者，则将用户信息同步到员工资料中
        return userWeixin;
    }
    @Override
    public List<UserWeixin> get8RealName(String name){
        return dao.get8RealName(name);
    }
    @Override
    public List<UserWeixin> getAllVisitor(){
        return dao.getAllVisitor();
    }
    @Override
    public UserWeixin get8UnionId(String unionId){
        return dao.get8UnionId(unionId);
    }
    @Override
    public void sync2Employee(UserWeixin record){
        if(record == null) return;
        Integer userType = Optional.ofNullable(record.getType()).orElse(RoleType.VISITOR_NORMAL.getId());// 默认是普通访客
        // 只有受访者才会继续向下执行，其他角色都退出不执行后面的逻辑
        if(userType < RoleType.INTERVIEWEE_NORMAL.getId()) return;
        if(userType > RoleType.INTERVIEWEE_ADMIN.getId()) return;

        String realName = Optional.ofNullable(record.getRealName()).orElse("");
        List<Employee> employeeList = employeeMapper.get8sname(realName);
        if(employeeList == null || employeeList.size() == 0)
            throw new BusinessException("没有员工" + realName + "，无法注册！");

        Employee employee = employeeList.get(0);
        String openId = Optional.ofNullable(employee.getOpenId()).orElse("");
        String miniId = Optional.ofNullable(employee.getMiniId()).orElse("");
        String unionId = Optional.ofNullable(employee.getUnionId()).orElse("");
        if(openId.length() <= 0) employee.setOpenId(record.getOpenId());
        if(miniId.length() <= 0) employee.setMiniId(record.getMiniId());
        if(unionId.length() <= 0) employee.setUnionId(record.getUnionId());
        employeeMapper.update(employee);
    }
}
